/**
 * Copyright (c) 2006-2020, zwl
 * 
 * description 常用功能函数
 * 
 * Change Logs:
 * Date             Author         Notes
 * 2021-01-08       Zwl             创建
 * 
 */
#include "EntTypeFramework.h"

#if ETF_CO_AUTOSTART_ENABLE && ETF_COROUTINE_EN
extern etf_err_t (* const autostart_processes[])(void);
#endif

/**
 *  字符串复制
 *
 *@param :  dst     ：目标地址
 *          src     ：源地址
 *          n       ：最大复制长度
 *@return:  目标地址
 *
 *@note  : 
 *
 *
 */
char *etf_strncpy(char *dst, const char *src, etf_uint32_t n){

    if (n != 0){
        char *d = dst;
        const char *s = src;

        do{
            if ((*d++ = *s++) == 0){
                /* NUL pad the remaining n-1 bytes */
                while (--n != 0)
                    *d++ = 0;
                break;
            }
        } while (--n != 0);
    }

    return (dst);
}

/**
 *  对比两个字符串指定长度的内容是否一致
 *
 *@param :  cs      ：要比较的字符串
 *          ct      ：要比较的字符串
 *          count   ：要比较的最大长度
 *
 *@return:  比对结果
 *
 *@note  : 
 *
 *
 */
etf_int32_t etf_strncmp(const char *cs, const char *ct, etf_uint32_t count){
    register signed char __res = 0;

    while (count)
    {
        if ((__res = *cs - *ct++) != 0 || !*cs++)
            break;
        count --;
    }

    return __res;
}

/**
 *  获取字符串长度
 *
 *@param :
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
etf_uint32_t etf_strlen(const char *s){
    const char *sc;
    
    for (sc = s; *sc != '\0'; ++sc) /* nothing */
    ;
    
    return sc - s;
}


/**
 *  获取字符串分隔符之前的长度
 *
 *@param :  cmdstr  ：需要分析的字符串；
 *          ch      ：分隔符；
 *
 *@return:  长度
 *
 *@note  : 
 *
 *
 */
etf_uint32_t etf_strlench(char *cmdstr, char ch){

    etf_uint32_t            len                     = 0;

    while( (*cmdstr != ch) && (*cmdstr != '\0') ){
        cmdstr++;
        len++;
    }

    return len;
}

/**
 *  对比两个字符串一样的长度；
 *
 *@param :  cmdstr  ：需要分析的字符串；
 *          ch      ：分隔符；
 *
 *@return:  长度
 *
 *@note  : 
 *
 *
 */
etf_uint16_t etf_strstrlen(char *src, char *obj){

    etf_uint16_t            len                     = 0;
  
    while( ('\0' != *src) && ('\0' != *obj) && ((*src) == (*obj) ) ){
        len++;
        src++;
        obj++;
    }
  
    return len;
}

/**
 *  整数转换为字符串
 *
 *@param :  num：需要转换的整数；
 *          str：存放转换后的字符串；
 *          radix：转换进制数(2、8、10、16)；
 *
 *@return:  转换后字符串地址；
 *
 *@note  : 
 *
 *
 */
char* etf_itoa(etf_int32_t num, char* str, etf_int32_t radix){

    char                            index[]                 ="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";    //索引表
    etf_uint32_t                    unum;                                                           //存放要转换的整数的绝对值,转换的整数可能是负数
    etf_int32_t                     i =0,j,k;                                                       //i用来指示设置字符串相应位，转换之后i其实就是字符串的长度；转换后顺序是逆序的，有正负的情况，k用来指示调整顺序的开始位置;j用来指示调整顺序时的交换。
    char                            temp;                                                           //临时变量，交换两个值时用到

    //获取要转换的整数的绝对值
    if( 10 == radix && 0 > num ){
        //要转换成十进制数并且是负数
        unum                                                =(etf_uint32_t) - num;                  //将num的绝对值赋给unum
        str[i++]                                            ='-';                                   //在字符串最前面设置为'-'号，并且索引加1
    }
    else{
        unum                                                = (etf_uint32_t)num;                    //若是num为正，直接赋值给unum
    }
 
    //转换部分，注意转换后是逆序的
    do{
        str[i++]                                            = index[unum%(etf_uint32_t)radix];      //取unum的最后一位，并设置为str对应位，指示索引加1
        unum                                               /= radix;                                //unum去掉最后一位
 
    }while(unum);                                                                                   //直至unum为0退出循环
 
    str[i]                                                  = '\0';                                 //在字符串最后添加'\0'字符，c语言字符串以'\0'结束。
 
    //将顺序调整过来
    if('-' == str[0]){
        k                                                   = 1;                                    //如果是负数，符号不用调整，从符号后面开始调整
    } else {
        k                                                   = 0;                                    //不是负数，全部都要调整
    }
 
    //头尾一一对称交换，i其实就是字符串的长度，索引最大值比长度少1
    for(j = k; j <= (i-1)/2; j++){
        temp                                                = str[j];                               //头部赋值给临时变量
        str[j]                                              = str[i-1+k-j];                         //尾部赋值给头部
        str[i-1+k-j]                                        = temp;                                 //将临时变量的值(其实就是之前的头部值)赋给尾部
    }

    //返回转换后的字符串
    return str;
}

/**
 *  事件类型框架各模块初始化
 *
 *@param :
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
void etf_module_init(void){

#if ETF_DEVICE_EN                       //设备框架初始化
    etf_device_module_init();
#endif
  
#if ETF_COROUTINE_EN                    //协程框架初始化
    etf_coroutine_module_init();
#endif
  
#if ETF_EVENT_EN                        //事件框架初始化
    etf_event_module_init();
#endif
  
#if ETF_TIMER_EN                        //定时器框架初始化
    etf_timer_module_init();
#endif

#if USE_SLOG
    SlogInit();                         //slog组件初始化
#endif




/* 自启动 */
#if ETF_CO_AUTOSTART_ENABLE && ETF_COROUTINE_EN
    etf_co_autostart_start(autostart_processes);
#endif
}

/**
 *  框架运行处理函数
 *
 *@param :
 *
 *@return:  是否有待处理事件
 *
 *@note  : 
 *
 *
 */
etf_uint32_t etf_run(void){

    etf_uint32_t                    res             = 0;
	
    etf_timer_run();
	
    res                                            += etf_coroutine_run();
    res                                            += etf_event_run();

    return res;
}

/**
 *  协程自启动处理
 *
 *@param :
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
void etf_co_autostart_start(etf_err_t (* const processes[])(void)){

  etf_uint32_t                      i               = 0;
  
  while(ETF_NULL != processes[i]) {
    processes[i]();
    i++;
  }
  
}

